/**
 * 
 */
package org.lora.biz.ou.group.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.lora.biz.ou.LoraOUConstant;
import org.lora.biz.ou.entity.EmployeeIdentity;
import org.lora.biz.ou.entity.EmployeeIdentityView;
import org.lora.biz.ou.entity.EmployeeIdentityViewExample;
import org.lora.biz.ou.entity.Organization;
import org.lora.biz.ou.exception.LoraOrgUserException;
import org.lora.biz.ou.group.entity.Group;
import org.lora.biz.ou.group.entity.GroupEI;
import org.lora.biz.ou.group.entity.GroupEIExample;
import org.lora.biz.ou.group.entity.GroupExample;
import org.lora.biz.ou.group.entity.GroupFormula;
import org.lora.biz.ou.group.entity.GroupFormulaExample;
import org.lora.biz.ou.group.mapper.GroupEIMapper;
import org.lora.biz.ou.group.mapper.GroupFormulaMapper;
import org.lora.biz.ou.group.mapper.GroupMapper;
import org.lora.biz.ou.group.service.IGroupService;
import org.lora.biz.ou.mapper.EmployeeIdentityViewMapper;
import org.lora.biz.ou.service.IEmployeeIdentityService;
import org.lora.biz.ou.service.IOrganizationService;
import org.lora.core.annotation.AutoAssemble;
import org.lora.core.annotation.Service;
import org.lora.core.mybatis.Page;
import org.lora.util.StringUtil;
import org.lora.util.ValidateUtil;
import org.lora.webframework.common.FrameWorkBaseService;

/**
 * <p>
 * 类名:GroupServiceImpl
 * </p>
 * 描述:群组服务实现<br>
 * 创建时间:2016年9月22日 下午4:00:11<br>
 * 
 * @author Bladnir@outlook.com<br>
 *         修改历史:<br>
 *         2016年9月22日 Bladnir 创建<br>
 */
@Service
public class GroupServiceImpl extends FrameWorkBaseService implements IGroupService {

	@AutoAssemble
	private GroupMapper groupMapper;

	@AutoAssemble
	private GroupEIMapper groupEIMapper;

	@AutoAssemble
	private GroupFormulaMapper groupFormulaMapper;

	@AutoAssemble
	private EmployeeIdentityViewMapper employeeIdentityViewMapper;

	@AutoAssemble
	private IEmployeeIdentityService employeeIdentityService;

	@AutoAssemble
	private IOrganizationService organizationService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupListByDomainId(java
	 * .lang.String)
	 */
	@Override
	public List<Group> getGroupListByDomainId(String domainId) throws LoraOrgUserException {

		GroupExample example = new GroupExample();
		example.createCriteria().andDomainIdEqualTo(domainId);

		return groupMapper.selectByExample(example);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupMember(java.lang.
	 * String, java.lang.String, org.lora.core.mybatis.Page)
	 */
	@Override
	public List<EmployeeIdentityView> getGroupMember(String groupId, String submitIdentityId, String draftIdentityId, Page page)
			throws LoraOrgUserException {

		Group group = getGroupById(groupId);
		if (group == null) {
			throw new LoraOrgUserException("getGroup Fail groupId=[" + groupId + "]");
		}

		return getGroupMember(group, submitIdentityId, draftIdentityId, page);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupMemberCount(java.
	 * lang.String, java.lang.String)
	 */
	@Override
	public int getGroupMemberCount(String groupId, String submitIdentityId, String draftIdentityId) throws LoraOrgUserException {

		Group group = getGroupById(groupId);
		if (group == null) {
			throw new LoraOrgUserException("getGroup Fail groupId=[" + groupId + "]");
		}

		int result = 0;
		if (group.getType().equals(LoraOUConstant.GROUP_TYPE_FIXED)) {
			// 固定人员
			GroupEIExample groupEIExample = new GroupEIExample();
			groupEIExample.createCriteria().andGroupIdEqualTo(groupId);
			result = groupEIMapper.countByExample(groupEIExample);
		} else if (group.getType().equals(LoraOUConstant.GROUP_TYPE_CALCULATE)) {
			// 无法分页 也不用计算数量了
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#addEIToGroup(java.lang.String
	 * , java.util.List)
	 */
	@Override
	public void addEIToGroup(String groupId, List<String> eiIdList) throws LoraOrgUserException {
		Group group = getGroupById(groupId);
		if (group == null) {
			throw new LoraOrgUserException("getGroup Fail groupId=[" + groupId + "]");
		}

		for (String eiId : eiIdList) {
			if (StringUtil.isNull(eiId)) {
				throw new LoraOrgUserException("addEIToGroup eiId is null");
			}

			GroupEI groupEI = new GroupEI();

			groupEI.setEiId(eiId);
			groupEI.setGroupId(groupId);

			groupEIMapper.insert(groupEI);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupById(java.lang.String
	 * )
	 */
	@Override
	public Group getGroupById(String groupId) throws LoraOrgUserException {

		if (StringUtil.isNull(groupId)) {
			throw new LoraOrgUserException("getGroupById groupId is null");
		}

		Group group = null;

		GroupExample example = new GroupExample();
		example.createCriteria().andIdEqualTo(groupId);
		List<Group> groupList = groupMapper.selectByExample(example);

		if (ValidateUtil.isNotEmpty(groupList)) {
			group = groupList.get(0);
		}

		return group;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupByNumber(java.lang
	 * .String)
	 */
	@Override
	public Group getGroupByNumber(String serialNumber) throws LoraOrgUserException {
		if (StringUtil.isNull(serialNumber)) {
			throw new LoraOrgUserException("getGroupByNumber serialNumber is null");
		}

		Group group = null;

		GroupExample example = new GroupExample();
		example.createCriteria().andSerialNumberEqualTo(serialNumber);
		List<Group> groupList = groupMapper.selectByExample(example);

		if (ValidateUtil.isNotEmpty(groupList)) {
			group = groupList.get(0);
		}

		return group;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupMember(org.lora.biz
	 * .ou.group.entity.Group, java.lang.String, org.lora.core.mybatis.Page)
	 */
	@Override
	public List<EmployeeIdentityView> getGroupMember(Group group, String submitIdentityId, String draftIdentityId, Page page)
			throws LoraOrgUserException {
		List<EmployeeIdentityView> resultList = new ArrayList<>();

		if (group.getType().equals(LoraOUConstant.GROUP_TYPE_FIXED)) {
			// 固定人员
			Map<String, Object> parameterMap = new HashMap<>();
			parameterMap.put("groupId", group.getId());
			resultList = groupEIMapper.selectEIByGroupId(parameterMap, page);
		} else if (group.getType().equals(LoraOUConstant.GROUP_TYPE_CALCULATE)) {
			// 获取动态群组中的身份
			resultList = getGroupMemberByFormula(group, submitIdentityId, draftIdentityId);
		}

		return resultList;
	}

	/**
	 * 获取动态群组中的身份
	 * 
	 * @param group
	 * @param submitIdentityId
	 * @param draftIdentityId
	 * @return
	 * @throws LoraOrgUserException
	 */
	protected List<EmployeeIdentityView> getGroupMemberByFormula(Group group, String submitIdentityId, String draftIdentityId)
			throws LoraOrgUserException {

		List<EmployeeIdentityView> resultList = new ArrayList<>();

		// 查询群组对应的公式
		GroupFormulaExample example = new GroupFormulaExample();
		example.createCriteria().andGroupIdEqualTo(group.getId());
		List<GroupFormula> groupFormulaList = groupFormulaMapper.selectByExample(example, null);

		if (ValidateUtil.isEmpty(groupFormulaList)) {
			super.businessLog.info("GroupNumber[" + group.getSerialNumber() + "] has no Formula");
			return resultList;
		}

		if (hasAllGroup(groupFormulaList)) {// 有所有人 这个条件 直接过滤域下面的所有有效身份

			EmployeeIdentityViewExample employeeIdentityViewExample = new EmployeeIdentityViewExample();

			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = employeeIdentityViewExample.createCriteria();
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			resultList = employeeIdentityViewMapper.selectByExample(employeeIdentityViewExample, null);

		} else {// 分别计算每个公式获得的身份 然后合并

			// 用于去掉重复身份
			List<String> eiIdList = new ArrayList<>();

			for (GroupFormula groupFormula : groupFormulaList) {
				// 获取公式对应的身份列表
				List<EmployeeIdentityView> eiList = getFormulaEiList(groupFormula, group, submitIdentityId, draftIdentityId);
				// 合并身份列表
				mergeEiList(resultList, eiIdList, eiList);
			}

		}

		return resultList;

	}

	/**
	 * 合并身份列表
	 * 
	 * @param resultList
	 * @param eiIdList
	 * @param eiList
	 */
	private void mergeEiList(List<EmployeeIdentityView> resultList, List<String> eiIdList, List<EmployeeIdentityView> eiList) {
		for (EmployeeIdentityView employeeIdentityView : eiList) {

			if (eiIdList.contains(employeeIdentityView.getEiId())) {
				continue;
			} else {
				eiIdList.add(employeeIdentityView.getEiId());
				resultList.add(employeeIdentityView);
			}

		}
	}

	/**
	 * 获取公式对应的身份
	 * 
	 * @param groupFormula
	 * @param group
	 * @param submitIdentityId
	 * @param draftIdentityId
	 * @return
	 * @throws LoraOrgUserException
	 */
	protected List<EmployeeIdentityView> getFormulaEiList(GroupFormula groupFormula, Group group, String submitIdentityId,
			String draftIdentityId) throws LoraOrgUserException {

		List<EmployeeIdentityView> resultList = new ArrayList<>();

		if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ORG_INSIDE)) {
			// 所在组织内的

			// 获取参与者的身份实体
			EmployeeIdentity employeeIdentity = getTakePart(submitIdentityId, draftIdentityId, groupFormula, group);

			EmployeeIdentityViewExample example = new EmployeeIdentityViewExample();
			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = example.createCriteria();

			criteria.andOrgIdEqualTo(employeeIdentity.getOrgId());
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			if (StringUtil.isNotNull(groupFormula.getPositionId())) {
				criteria.andPositionIdEqualTo(groupFormula.getPositionId());
			}

			resultList = employeeIdentityViewMapper.selectByExample(example, null);

		} else if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ORG_UP)) {
			// 所在组织的上级组织

			// 获取参与者的身份实体
			EmployeeIdentity employeeIdentity = getTakePart(submitIdentityId, draftIdentityId, groupFormula, group);

			List<Organization> orgList = organizationService.getAllParentOrganization(group.getDomainId(), employeeIdentity.getOrgId());
			if (ValidateUtil.isEmpty(orgList) || orgList.size() == 1) {
				// 获取不到上级组织
				return resultList;
			}

			// 上级组织ID
			String orgId = orgList.get(1).getId();

			EmployeeIdentityViewExample example = new EmployeeIdentityViewExample();
			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = example.createCriteria();

			criteria.andOrgIdEqualTo(orgId);
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			if (StringUtil.isNotNull(groupFormula.getPositionId())) {
				criteria.andPositionIdEqualTo(groupFormula.getPositionId());
			}

			resultList = employeeIdentityViewMapper.selectByExample(example, null);

		} else if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ORG_DOWN)) {
			// 所在组织及其下级组织

			// 获取参与者的身份实体
			EmployeeIdentity employeeIdentity = getTakePart(submitIdentityId, draftIdentityId, groupFormula, group);

			List<Organization> orgList = organizationService.getAllChildrenOrganization(group.getDomainId(), employeeIdentity.getOrgId());
			if (ValidateUtil.isEmpty(orgList) || orgList.size() == 1) {
				// 获取不到子组织
				return resultList;
			}

			List<String> orgIdList = new ArrayList<>();
			for (Organization organization : orgList) {
				orgIdList.add(organization.getId());
			}

			EmployeeIdentityViewExample example = new EmployeeIdentityViewExample();
			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = example.createCriteria();

			criteria.andOrgIdIn(orgIdList);
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			if (StringUtil.isNotNull(groupFormula.getPositionId())) {
				criteria.andPositionIdEqualTo(groupFormula.getPositionId());
			}

			resultList = employeeIdentityViewMapper.selectByExample(example, null);
		} else if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ORG_FIX)) {
			// 指定组织内的
			String orgId = groupFormula.getOrgId();

			EmployeeIdentityViewExample example = new EmployeeIdentityViewExample();
			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = example.createCriteria();

			criteria.andOrgIdEqualTo(orgId);
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			if (StringUtil.isNotNull(groupFormula.getPositionId())) {
				criteria.andPositionIdEqualTo(groupFormula.getPositionId());
			}

			resultList = employeeIdentityViewMapper.selectByExample(example, null);

		} else if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ORG_FIX_DOWN)) {
			// 指定组织及其下级组织内的
			String orgId = groupFormula.getOrgId();

			List<Organization> orgList = organizationService.getAllChildrenOrganization(group.getDomainId(), orgId);
			if (ValidateUtil.isEmpty(orgList) || orgList.size() == 1) {
				// 获取不到子组织
				return resultList;
			}

			List<String> orgIdList = new ArrayList<>();
			for (Organization organization : orgList) {
				orgIdList.add(organization.getId());
			}

			EmployeeIdentityViewExample example = new EmployeeIdentityViewExample();
			org.lora.biz.ou.entity.EmployeeIdentityViewExample.Criteria criteria = example.createCriteria();

			criteria.andOrgIdIn(orgIdList);
			criteria.andDomainIdEqualTo(group.getDomainId());
			criteria.andEiStateEqualTo(LoraOUConstant.STATE_ACTIVATE);
			if (StringUtil.isNotNull(groupFormula.getPositionId())) {
				criteria.andPositionIdEqualTo(groupFormula.getPositionId());
			}

			resultList = employeeIdentityViewMapper.selectByExample(example, null);

		}

		return resultList;
	}

	/**
	 * 获取参与者
	 * 
	 * @param submitIdentityId
	 * @param draftIdentityId
	 * @param groupFormula
	 * @param group
	 * @return
	 * @throws LoraOrgUserException
	 */
	protected EmployeeIdentity getTakePart(String submitIdentityId, String draftIdentityId, GroupFormula groupFormula, Group group)
			throws LoraOrgUserException {

		String takePartId = "";

		if (ValidateUtil.isEqual(groupFormula.getTakePart(), LoraOUConstant.GRPUP_TAKEPART_DRAFTER)) {
			takePartId = draftIdentityId;
		} else if (ValidateUtil.isEqual(groupFormula.getTakePart(), LoraOUConstant.GROUP_TAKEPART_SUBMITER)) {
			takePartId = submitIdentityId;
		}

		if (StringUtil.isNull(takePartId)) {
			throw new LoraOrgUserException("getFormulaEiList takePartId is null takePartType=[" + groupFormula.getTakePart() + "]");
		}

		EmployeeIdentity employeeIdentity = employeeIdentityService.getEmployeeIdentityById(group.getDomainId(), takePartId);
		if (employeeIdentity == null) {
			throw new LoraOrgUserException("getFormulaEiList getEmployeeIdentity Fail id=[" + takePartId + "] domainId=["
					+ group.getDomainId() + "]");
		}

		return employeeIdentity;
	}

	/**
	 * 判断条件中是否有 所有人这种条件
	 * 
	 * @param groupFormulaList
	 * @return
	 */
	protected boolean hasAllGroup(List<GroupFormula> groupFormulaList) {

		boolean flag = false;

		for (GroupFormula groupFormula : groupFormulaList) {
			if (ValidateUtil.isEqual(groupFormula.getFormulaType(), LoraOUConstant.GROUP_TYPE_ALL)) {
				flag = true;
				break;
			}
		}

		return flag;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#deleteEIToGroup(java.lang
	 * .String, java.util.List)
	 */
	@Override
	public void deleteEIToGroup(String groupId, List<String> eiIdList) throws LoraOrgUserException {

		Group group = getGroupById(groupId);
		if (group == null) {
			throw new LoraOrgUserException("getGroup Fail groupId=[" + groupId + "]");
		}

		if (ValidateUtil.isEmpty(eiIdList)) {
			return;
		}

		GroupEIExample example = new GroupEIExample();
		org.lora.biz.ou.group.entity.GroupEIExample.Criteria criteria = example.createCriteria();
		criteria.andGroupIdEqualTo(groupId);
		criteria.andEiIdIn(eiIdList);

		groupEIMapper.deleteByExample(example);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#insertGroupFormula(org.lora
	 * .biz.ou.group.entity.GroupFormula)
	 */
	@Override
	public int insertGroupFormula(GroupFormula groupFormula) throws LoraOrgUserException {

		groupFormula.setId(super.creatBeanId(LoraOUConstant.ORG_FORMULA_PREFIX));
		return groupFormulaMapper.insert(groupFormula);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#deleteGroupFormulaById(java
	 * .util.List)
	 */
	@Override
	public int deleteGroupFormulaById(List<String> groupFormulaIdList) throws LoraOrgUserException {

		GroupFormulaExample example = new GroupFormulaExample();

		org.lora.biz.ou.group.entity.GroupFormulaExample.Criteria criteria = example.createCriteria();

		criteria.andIdIn(groupFormulaIdList);

		return groupFormulaMapper.deleteByExample(example);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupFormulaList(java.
	 * lang.String, org.lora.core.mybatis.Page)
	 */
	@Override
	public List<GroupFormula> getGroupFormulaList(String groupId, Page page) throws LoraOrgUserException {
		GroupFormulaExample example = new GroupFormulaExample();
		example.createCriteria().andGroupIdEqualTo(groupId);

		return groupFormulaMapper.selectByExample(example, page);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#getGroupFormulaListCount(
	 * java.lang.String, org.lora.core.mybatis.Page)
	 */
	@Override
	public int getGroupFormulaListCount(String groupId) throws LoraOrgUserException {
		GroupFormulaExample example = new GroupFormulaExample();
		example.createCriteria().andGroupIdEqualTo(groupId);
		return groupFormulaMapper.countByExample(example);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#addGroupAndType(org.lora.
	 * biz.ou.group.entity.Group)
	 */
	@Override
	public int addGroupAndType(Group group) throws LoraOrgUserException {

		if (StringUtil.isNull(group.getId())) {
			// insert
			group.setId(super.creatBeanId(LoraOUConstant.GROUP_PREFIX));
			return groupMapper.insert(group);
		} else {
			// update
			GroupExample example = new GroupExample();
			example.createCriteria().andIdEqualTo(group.getId());
			return groupMapper.updateByExample(group, example);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.biz.ou.group.service.IGroupService#deleteGroupById(java.lang
	 * .String)
	 */
	@Override
	public int deleteGroupById(String groupId) throws LoraOrgUserException {
		Group group = getGroupById(groupId);
		if (group == null) {
			super.businessLog.info("groupId=[" + groupId + "] cant find Group");
			return 0;
		}

		List<String> groupIdList = new ArrayList<>();
		groupIdList.add(groupId);

		String groupType = group.getType();
		if (ValidateUtil.isEqual(groupType, LoraOUConstant.GROUP_TYPE_TYPE)) {
			// 群组类型

			// 获取类型下的所有群组
			GroupExample example = new GroupExample();
			example.createCriteria().andParentIdEqualTo(groupId);
			List<Group> groupList = groupMapper.selectByExample(example);

			for (Group childrenGroup : groupList) {
				groupIdList.add(childrenGroup.getId());

				// 删除群组对应的身份和公式
				deleteGroupContent(childrenGroup);
			}

		} else if (ValidateUtil.isEqual(groupType, LoraOUConstant.GROUP_TYPE_CALCULATE)
				|| ValidateUtil.isEqual(groupType, LoraOUConstant.GROUP_TYPE_FIXED)) {
			// 动态计算群组 和 固定人员群组

			// 删除群组对应的身份和公式
			deleteGroupContent(group);

		}

		// 删除群组 和 群组类型
		return deleteRealGroup(groupIdList);
	}

	/**
	 * 根据ID直接删除群组
	 * 
	 * @param groupIdList
	 * @return
	 */
	public int deleteRealGroup(List<String> groupIdList) {
		if (ValidateUtil.isEmpty(groupIdList)) {
			return 0;
		}

		GroupExample example = new GroupExample();
		example.createCriteria().andIdIn(groupIdList);
		return groupMapper.deleteByExample(example);
	}

	/**
	 * 删除群组对应的身份和公式
	 * 
	 * @param group
	 */
	public void deleteGroupContent(Group group) {

		String groupType = group.getType();

		if (ValidateUtil.isEqual(groupType, LoraOUConstant.GROUP_TYPE_CALCULATE)) {
			// 动态计算群组 删除对应的公式

			GroupFormulaExample example = new GroupFormulaExample();
			example.createCriteria().andGroupIdEqualTo(group.getId());

			groupFormulaMapper.deleteByExample(example);

		} else if (ValidateUtil.isEqual(groupType, LoraOUConstant.GROUP_TYPE_FIXED)) {
			// 固定人员群组 删除对应的身份

			GroupEIExample example = new GroupEIExample();

			example.createCriteria().andGroupIdEqualTo(group.getId());

			groupEIMapper.deleteByExample(example);

		}
	}

}
